home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / LispExample / Lisp.m < prev    next >
Text File  |  1995-06-12  |  4KB  |  194 lines

  1. /*
  2. **    Lisp.m
  3. **    Lisp client object with message-based I/O.
  4. **    Lee Boynton, NeXT, Inc., 1989
  5. */
  6.  
  7. #import <mach.h>
  8. #import <stdlib.h>
  9. #import <string.h>
  10. #import <fcntl.h>
  11. #import <signal.h>
  12. #import <sys/wait.h>
  13. #import <dpsclient/dpsclient.h>
  14. #import <defaults/defaults.h>
  15. #import <appkit/Application.h>
  16. #import <objc/List.h>
  17. #import "Lisp.h"
  18.  
  19. @implementation Lisp
  20.  
  21. #define READ_BUF_SIZE (8191)
  22. static char read_buf[READ_BUF_SIZE+1];
  23.  
  24. static void *read_lisp(int fd, Lisp *self)
  25. {
  26.     extern int read();
  27.     NXEvent event;
  28.     int count = read(fd,read_buf,READ_BUF_SIZE);
  29.     id delegate = self->delegate;
  30.     BOOL tellDelegate = NO;
  31.     if (delegate  && [delegate respondsTo:@selector(lispOutput:)])
  32.     tellDelegate = YES;
  33.     while (count > 0) {
  34.     read_buf[count] = '\0';
  35.     if (tellDelegate)
  36.         [delegate lispOutput:(const char *)read_buf];
  37.     if ([NXApp peekNextEvent:-1 into:&event waitFor:0.0 threshold:1])
  38.         break;
  39.     count = read(fd,read_buf,READ_BUF_SIZE);
  40.     }
  41. }
  42.  
  43. static int launch(const char *name, const char **argv, 
  44.           int *child_pid,
  45.           int *write_child_fd, int *read_child_fd)
  46. {
  47.     extern int pipe();
  48.     extern int fork();
  49.     extern int dup2();
  50.     extern int close();
  51.     extern int execvp();
  52.     extern int fcntl();
  53.     extern int close();
  54.     int err, pid;
  55.     int p_to_child[2], p_from_child[2];
  56.  
  57.     if ((err = pipe(p_to_child)) < 0)
  58.     return err;
  59.     if ((err = pipe(p_from_child)) < 0) {
  60.     close(p_to_child[0]);
  61.     close(p_to_child[1]);
  62.     return err;
  63.     }
  64.     if ((pid = fork()) == 0) {
  65.     dup2(p_to_child[0], 0);
  66.     dup2(p_from_child[1], 1);
  67.     dup2(p_from_child[1], 2);
  68.     close(p_to_child[1]);
  69.     close(p_from_child[0]);
  70.     execvp(name, argv);
  71.     exit(127);
  72.     }
  73.     if (pid == -1) {
  74.     close(p_to_child[0]);
  75.     close(p_to_child[1]);
  76.     close(p_from_child[0]);
  77.     close(p_from_child[1]);
  78.     return -1;
  79.     }
  80.     *child_pid = pid;
  81.     *write_child_fd = p_to_child[1];
  82.     close(p_to_child[0]);
  83.     *read_child_fd = p_from_child[0];
  84.     close(p_from_child[1]);
  85.     return fcntl(*read_child_fd,F_SETFL,FNDELAY);
  86. }
  87.  
  88.  
  89. static id lispList = nil;
  90.  
  91. static id findLispForPid(int pid) {
  92.     Lisp *self;
  93.     int i, max = [lispList count];
  94.     for (i=0; i<max; i++) {
  95.     self = (Lisp *)[lispList objectAt:i];
  96.     if (self->lisp_pid == pid)
  97.         return self;
  98.     }
  99.     return nil;
  100. }
  101.  
  102. static void lispDied(int ignore) {
  103.     union wait epitaph;
  104.     int pid;
  105.     Lisp *self;
  106.     
  107.     while (1) {
  108.     pid = wait3(&epitaph,WNOHANG,0);
  109.     if (pid > 0) {
  110.         if (self = findLispForPid(pid)) {
  111.         self->lisp_pid = 0;
  112.         break;
  113.         }
  114.     } else
  115.         break;
  116.     }
  117.     signal(SIGCHLD,&lispDied);
  118. }
  119.  
  120. + initialize
  121. {
  122.     if (!lispList)
  123.     lispList = [List new];
  124.     signal(SIGCHLD,&lispDied);
  125.     return self;
  126. }
  127.  
  128. + new
  129. {
  130.     int err;
  131.     const char *argv[2];
  132.     const char *imageName = NXGetDefaultValue([NXApp appName],"LispImage");
  133.     self = [super new];
  134.     argv[0] = imageName;
  135.     argv[1] = NULL;
  136.     [lispList addObject:self];
  137.     err = launch(imageName,argv,&lisp_pid, &lisp_in_fd,&lisp_out_fd);
  138.     if (err) {
  139.     [self free];
  140.     return nil;
  141.     }
  142.     DPSAddFD(lisp_out_fd,(DPSFDProc)read_lisp,(void *)self,1);
  143.     return self;
  144. }
  145.  
  146. - free
  147. {
  148.     extern int kill();
  149.     DPSRemoveFD(lisp_out_fd);
  150.     [lispList removeObject:self];
  151.     if (lisp_pid)
  152.     kill(lisp_pid,9);
  153.     return [super free];
  154. }
  155.  
  156. - setDelegate:anObject
  157. {
  158.     delegate = anObject;
  159.     return self;
  160. }
  161.  
  162. - delegate
  163. {
  164.     return delegate;
  165. }
  166.  
  167. - inputLisp:(const char *)theString
  168. {
  169.     extern int write();
  170.     int i, count = strlen(theString);
  171.     if (!lisp_pid || (count != write(lisp_in_fd,theString,count)))
  172.     return nil;
  173.     return self;
  174. }
  175.  
  176. - interruptLisp
  177. {
  178.     extern int kill();
  179.     if (lisp_pid && kill(lisp_pid,2))
  180.     return nil;
  181.     return self;
  182. }
  183.  
  184. @end
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.